# coding:utf-8
import importlib
import json
import shutil
from typing import Dict
import traceback

from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QWidget
from loguru import logger
from qfluentwidgets import FluentWindow, FluentIcon as FIF, MessageBox

from .settings import PLUGINS_DIR, PLUGIN_CONFIG_FILE


class AppPluginBase(object):
    config = {}
    icon = FIF.APPLICATION

    def __init__(self, iface: FluentWindow):
        self.iface = iface
        self.subWidget: QWidget = None

    def setSubWidgt(self, sub_widget: QWidget):
        self.subWidget = sub_widget

    def load(self):
        config = self.config
        self.icon = config.get('icon', self.icon)

        self.iface.addSampleCard(
            self.icon,
            config.get('name', ''),
            config.get('description', ''),
            str(self.subWidget),
            getattr(self.iface, config.get('parent')),
            self.subWidget,
            config.get('is_shortcut', True),
        )

    def enabled(self):
        plugin_manager.enabled(self.config.get('path_name'))
        self.load()

    def disabled(self):
        plugin_manager.disabled(self.config.get('path_name', ''))
        self.iface.removeSampleCard(getattr(self.iface, self.config.get('parent')), str(self.subWidget))

    def unload(self, plugin_name: str):
        self.disabled()
        self.iface.removeSampleCard(getattr(self.iface, self.config.get('parent')), str(self.subWidget))
        shutil.rmtree(PLUGINS_DIR / plugin_name)

    def isEnabled(self):
        return self.config.get('enabled', True)

class PluginManager(object):
    def __init__(self):
        self.plugins: Dict[str, AppPluginBase] = {}

    def load_plugins(self, iface: FluentWindow):
        for plugin_dir in PLUGINS_DIR.iterdir():
            if not plugin_dir.is_dir():
                continue
            plugin_name = plugin_dir.name
            if plugin_name.startswith('__'):
                continue

            try:
                plugin_module = importlib.import_module(f'{PLUGINS_DIR.name}.{plugin_name}')
                plugin_class = getattr(plugin_module, 'Plugin')
                plugin = plugin_class(iface)
                config = self.plugin_settings(plugin_name)
                config.update({'path_name': plugin_name})
                plugin.config = config
                self.plugins[plugin_name] = plugin
                # 如果禁用，则不加载插件
                if self.isEnabled(plugin_name) is False:
                    continue
                plugin.load()
                logger.info(f'加载插件成功: {plugin_name}')
            except Exception as e:
                exception_str = traceback.format_exc()
                message_box = MessageBox(f'{plugin_name} 插件加载失败', exception_str, iface)
                message_box.contentLabel.setTextInteractionFlags(Qt.TextInteractionFlag.TextBrowserInteraction)
                message_box.setClosableOnMaskClicked(True)
                message_box.show()
                logger.error(exception_str)

    def unload_plugins(self):
        for key, plugin in self.plugins.items():
            plugin: AppPluginBase
            plugin.unload(PLUGINS_DIR / key)
        self.plugins.clear()

    def reload_plugins(self, iface: FluentWindow):
        self.unload_plugins()
        self.load_plugins(iface)

    def settings(self):
        if PLUGIN_CONFIG_FILE.exists():
            return json.loads(PLUGIN_CONFIG_FILE.read_text('utf-8'))
        else:
            dufault_config = {
                'all_plugins': [],
                'enabled_plugins': [],
                'disabled_plugins': []
            }
            PLUGIN_CONFIG_FILE.touch()
            PLUGIN_CONFIG_FILE.write_text(json.dumps(dufault_config, indent=4, ensure_ascii=False))
            return dufault_config

    def plugin_settings(self, plugin_name: str):
        """
        获取插件配置
        :param plugin_name:
        :return:
        """
        plugin_path = PLUGINS_DIR / plugin_name / 'config.json'
        if not plugin_path.exists():
            default_config = {
                'name': plugin_name,
                'description': '未知插件',
                'detailed_description': '该插件未提供详细描述',
                'author': '未知作者',
                'version': '1.0.0',
                'parent': 'otherInterface',
                'url': '',
                'enabled': True,
                'is_shortcut': True
            }
            plugin_path.write_text(json.dumps(default_config, indent=4, ensure_ascii=False), 'utf-8')
            return default_config
        else:
            return json.loads(plugin_path.read_text('utf-8'))

    def disabled(self, plugin_name: str):
        """
        禁用插件
        :param plugin_name:
        :return:
        """
        self.setEnabled(plugin_name, False)

    def enabled(self, plugin_name: str):
        """
        启用插件
        :param plugin_name:
        :return:
        """
        self.setEnabled(plugin_name, True)

    def isEnabled(self, plugin_name: str):
        """
        判断插件是否启用
        :param plugin_name:
        :return:
        """
        return self.plugin_settings(plugin_name).get('enabled', True)

    def setEnabled(self, plugin_name: str, enabled: bool):
        """
        设置插件是否启用
        :param plugin_name:
        :param enabled:
        :return:
        """
        config = self.plugin_settings(plugin_name)
        config['enabled'] = enabled
        plugin_path = PLUGINS_DIR / plugin_name / 'config.json'
        plugin_path.write_text(json.dumps(config, indent=4, ensure_ascii=False), 'utf-8')


plugin_manager = PluginManager()
